/**
 * Copyright (C) 2022 - 长期
 * All rights reserved.
 * <p>
 */
package com.itzhoun.config;

import com.itzhoun.config.shiro.JWTFilter;
import com.itzhoun.config.shiro.MyShiroRealm;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.core.annotation.Order;

import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author zhounan
 * @date 2024/01/22 14:27
 * @Description Shiro核心也是控制Filter来控制的，类似于SpringMVC通过DispatchServlet来控制一样
 * 既然是通过URL来控制，那么里面也是根据规则和权限校验逻辑判断，所以我们需要定义一下规则和逻辑校验判断
 *
 */
@Configuration
@Order(1)
public class ShiroConfig {

    /**
     *
     * @author zhounan
     * @Create 2024/1/22 14:42
     * @Description
     * ShiroFilterFactoryBean 处理拦截资源文件问题
     *
     * @param securityManager
     * @return org.apache.shiro.spring.web.ShiroFilterFactoryBean
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager){

        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //必须设置 SecurityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //验证码过滤器
        Map<String, Filter> filters = shiroFilterFactoryBean.getFilters();
        filters.put("jwt", new JWTFilter());
        shiroFilterFactoryBean.setFilters(filters);

        //拦截器
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        //swagger接口文档
        filterChainDefinitionMap.put("/v2/api-docs","anon");
        filterChainDefinitionMap.put("/webjars/**", "anon");
        filterChainDefinitionMap.put("/swagger-resources/**", "anon");
        filterChainDefinitionMap.put("/swagger-ui.html", "anon");
        filterChainDefinitionMap.put("/doc.html", "anon");

        filterChainDefinitionMap.put("/**", "jwt");


        //401 和 404filter不通过我们的页面
        filterChainDefinitionMap.put("/401", "anon");
        filterChainDefinitionMap.put("/404", "anon");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

    /**
     *
     * @author zhounan
     * @Create 2024/1/22 21:59
     * @Description 安全管理器  需要自己去配置realm
     * @return org.apache.shiro.mgt.SecurityManager
     */
    @Bean
    public SecurityManager securityManager(){
        DefaultSecurityManager defaultSecurityManager = new DefaultWebSecurityManager();
        //设置real
        defaultSecurityManager.setRealm(myShiroRealm());
        //注入缓存管理器
        defaultSecurityManager.setCacheManager(ehCacheManager());

        //关闭shiro自带的session
        DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
        defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
        DefaultSubjectDAO defaultSubjectDAO = new DefaultSubjectDAO();
        defaultSubjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
        defaultSecurityManager.setSubjectDAO(defaultSubjectDAO);
        return defaultSecurityManager;
    }

    /**
     *
     * @author zhounan
     * @Create 2024/1/22 21:56
     * @Description 开启shiro的aop注解
     * @param securityManager 安全管理器
     * @return org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor
     */
    @Bean("authorizationAttributeSourceAdvisor")
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }


    @Bean("lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    @DependsOn({"lifecycleBeanPostProcessor"})
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }


    /**
     *
     * @author zhounan
     * @Create 2024/1/22 19:26
     * @Description 身份认证realm
     * @return org.apache.shiro.realm.Realm
     */
    @Bean
    public Realm myShiroRealm(){
        return new MyShiroRealm();
    }



    /**
     *
     * @author zhounan
     * @Create 2024/1/22 19:25
     * @Description shiro缓存管理器
     * @return org.apache.shiro.cache.ehcache.EhCacheManager
     */
    @Bean
    public EhCacheManager ehCacheManager(){
        EhCacheManager ehCacheManager = new EhCacheManager();
        ehCacheManager.setCacheManagerConfigFile("classpath:ehcache.xml");
        return ehCacheManager;
    }
}
